package convert

import (
	"fmt"
	"reflect"
	"strings"
)

// ArrayToString 将接口数组转换为逗号分隔的字符串。
//
// 参数:
//   - array: 要转换的接口数组
//
// 返回值:
//   - string: 转换后的逗号分隔字符串
//
// 示例:
//
//	arr := []interface{}{1, "hello", true}
//	str := ArrayToString(arr) // 返回 "1,hello,true"
func ArrayToString(array []interface{}) string {
	return strings.Replace(strings.Trim(fmt.Sprint(array), "[]"), " ", ",", -1)
}

// StructToMap 将结构体转换为映射。
//
// 此函数将结构体的字段转换为键值对。如果结构体字段有"mapstructure"标签，
// 则使用该标签值作为键；否则使用字段名作为键。
//
// 参数:
//   - obj: 要转换的结构体对象
//
// 返回值:
//   - map[string]interface{}: 包含结构体字段的映射
//
// 示例:
//
//	type Person struct {
//	    Name string `mapstructure:"person_name"`
//	    Age  int
//	}
//	p := Person{Name: "Alice", Age: 30}
//	m := StructToMap(p) // 返回 {"person_name": "Alice", "Age": 30}
func StructToMap(obj interface{}) map[string]interface{} {
	obj1 := reflect.TypeOf(obj)
	obj2 := reflect.ValueOf(obj)

	data := make(map[string]interface{})
	for i := 0; i < obj1.NumField(); i++ {
		if obj1.Field(i).Tag.Get("mapstructure") != "" {
			data[obj1.Field(i).Tag.Get("mapstructure")] = obj2.Field(i).Interface()
		} else {
			data[obj1.Field(i).Name] = obj2.Field(i).Interface()
		}
	}
	return data
}

// ConvertArray2InterfaceArray 将任意类型的切片转换为接口切片。
//
// 参数:
//   - slice: 要转换的切片（任意类型）
//
// 返回值:
//   - []interface{}: 转换后的接口切片
//   - bool: 如果输入参数是切片则返回true，否则返回false
//
// 示例:
//
//	nums := []int{1, 2, 3}
//	interfaceArray, ok := ConvertArray2InterfaceArray(nums)
//	// 返回 [{1 2 3}], true
func ConvertArray2InterfaceArray(slice interface{}) ([]interface{}, bool) {
	val, ok := isSlice(slice)

	if !ok {
		return nil, false
	}

	sliceLen := val.Len()
	out := make([]interface{}, sliceLen)
	for i := 0; i < sliceLen; i++ {
		out[i] = val.Index(i).Interface()
	}

	return out, true
}

// isSlice 检查给定的参数是否为切片类型。
//
// 参数:
//   - arg: 要检查的参数
//
// 返回值:
//   - val: 参数的反射值
//   - ok: 如果参数是切片类型则返回true，否则返回false
//
// 示例:
//
//	nums := []int{1, 2, 3}
//	val, ok := isSlice(nums) // 返回 reflect.Value, true
//	str := "not a slice"
//	val, ok := isSlice(str) // 返回 reflect.Value, false
func isSlice(arg interface{}) (val reflect.Value, ok bool) {
	val = reflect.ValueOf(arg)

	if val.Kind() == reflect.Slice {
		ok = true
	}

	return
}
